package finder;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class MainFrame extends JFrame {
	
	private int shown;
	private ArrayList<ArrayList<Integer>> resList = new ArrayList<ArrayList<Integer>>();
	private ArrayList<JCheckBox> boxes = new ArrayList<JCheckBox>();
	
	private JPanel contentPane, resultPane;
	private JTextField tfRP;
	private JLabel lblRP, lblAmount, lblRes;
	private JButton btnRP, btnStop, btnMore;
	private JScrollPane spRP;
	private JSeparator sepV, sepH;
	private JCheckBox c3250, c1820, c1350, c975, c880, c790, c750, c675, c585,
					  c520, c487, c440, c395, c390, c375, c292, c260, c250;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainFrame frame = new MainFrame();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public MainFrame() {
		setTitle("0 RP Finder");
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			e1.printStackTrace();
		} catch (UnsupportedLookAndFeelException e1) {
			e1.printStackTrace();
		}
		setBounds(100, 100, 560, 300);
		
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(null);
		setContentPane(contentPane);
		
		sepV = new JSeparator(JSeparator.VERTICAL);
		sepV.setBounds(420, 5, 2, 225);
		contentPane.add(sepV);
		
		sepH = new JSeparator(JSeparator.HORIZONTAL);
		sepH.setBounds(420, 230, 130, 2);
		contentPane.add(sepH);
		
		lblRP = new JLabel("Enter your RP here");
		lblRP.setForeground(Color.BLACK);
		lblRP.setBounds(130, 8, 130, 15);
		contentPane.add(lblRP);
		
		lblAmount = new JLabel("You are willing to pay");
		lblAmount.setForeground(Color.BLACK);
		lblAmount.setBounds(437, 8, 120, 15);
		contentPane.add(lblAmount);
		
		lblRes = new JLabel("Results found: 55555");
		lblRes.setForeground(Color.BLACK);
		lblRes.setBounds(100, 120, 200, 15);
		lblRes.setVisible(false);
		contentPane.add(lblRes);
		
		tfRP = new JTextField();
		tfRP.setBounds(100, 25, 150, 25);
		contentPane.add(tfRP);
		
		btnRP = new JButton("Go!");
		btnRP.setOpaque(false);
		btnRP.setFocusPainted(false);
		btnRP.addActionListener(new GoListener());
		btnRP.setBounds(260, 27, 50, 21);
		contentPane.add(btnRP);
		
		btnStop = new JButton("Stop");
		btnStop.setOpaque(false);
		btnStop.setFocusPainted(false);
		btnStop.setBounds(120, 140, 60, 20);
		btnStop.setVisible(false);
		contentPane.add(btnStop);
		
		btnMore = new JButton("More");
		btnMore.setOpaque(false);
		btnMore.setFocusPainted(false);
		btnMore.setVisible(false);
		btnMore.addActionListener(new MoreListener());
		btnMore.setBounds(420, 240, 60, 20);
		contentPane.add(btnMore);
		
		spRP = new JScrollPane();
		spRP.getVerticalScrollBar().setPreferredSize(new Dimension(10, 10));
		spRP.getVerticalScrollBar().setUnitIncrement(10);
		spRP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		spRP.setBounds(5, 60, 405, 210);
		contentPane.add(spRP);
		
		resultPane = new JPanel();
		resultPane.setLayout(null);
		spRP.setViewportView(resultPane);
		
		c3250 = new JCheckBox("3250 RP");
		c1820 = new JCheckBox("1820 RP");
		c1350 = new JCheckBox("1350 RP");
		c975 = new JCheckBox("975 RP");
		c880 = new JCheckBox("880 RP");
		c790 = new JCheckBox("790 RP");
		c750 = new JCheckBox("750 RP");
		c675 = new JCheckBox("675 RP");
		c585 = new JCheckBox("585 RP");
		c520 = new JCheckBox("520 RP");
		c487 = new JCheckBox("487 RP");
		c440 = new JCheckBox("440 RP");
		c395 = new JCheckBox("395 RP");
		c390 = new JCheckBox("390 RP");
		c375 = new JCheckBox("375 RP");
		c292 = new JCheckBox("292 RP");
		c260 = new JCheckBox("260 RP");
		c250 = new JCheckBox("250 RP");
		
		boxes.add(c3250);
		boxes.add(c1820);
		boxes.add(c1350);
		boxes.add(c975);
		boxes.add(c880);
		boxes.add(c790);
		boxes.add(c750);
		boxes.add(c675);
		boxes.add(c585);
		boxes.add(c520);
		boxes.add(c487);
		boxes.add(c440);
		boxes.add(c395);
		boxes.add(c390);
		boxes.add(c375);
		boxes.add(c292);
		boxes.add(c260);
		boxes.add(c250);
		
		c3250.setBounds(425, 30, 65, 15);
		c1820.setBounds(425, 47, 65, 15);
		c1350.setBounds(425, 64, 65, 15);
		c975.setBounds(425, 81, 65, 15);
		c880.setBounds(425, 98, 65, 15);
		c790.setBounds(425, 115, 65, 15);
		c750.setBounds(425, 132, 65, 15);
		c675.setBounds(425, 149, 65, 15);
		c585.setBounds(425, 166, 65, 15);
		c520.setBounds(490, 30, 65, 15);
		c487.setBounds(490, 47, 65, 15);
		c440.setBounds(490, 64, 65, 15);
		c395.setBounds(490, 81, 65, 15);
		c390.setBounds(490, 98, 65, 15);
		c375.setBounds(490, 115, 65, 15);
		c292.setBounds(490, 132, 65, 15);
		c260.setBounds(490, 149, 65, 15);
		c250.setBounds(490, 166, 65, 15);
		
		c3250.setToolTipText("Ultimate Skin");
		c1820.setToolTipText("Legendary Skin");
		c1350.setToolTipText("High-Tier Skin");
		c975.setToolTipText("6300 Champ/Normal Skin");
		c880.setToolTipText("4800 Champ");
		c790.setToolTipText("3150 Champ");
		c750.setToolTipText("Medium-Tier Skin");
		c675.setToolTipText("High-Tier Skin on sale");
		c585.setToolTipText("1350 Champ");
		c520.setToolTipText("Low-Tier Skin");
		c487.setToolTipText("6300 Champ/Normal Skin on sale");
		c440.setToolTipText("4800 Champ on sale");
		c395.setToolTipText("3150 Champ on sale");
		c390.setToolTipText("Bottom-Tier Skin");
		c375.setToolTipText("Medium-Tier Skin on sale");
		c292.setToolTipText("1350 Champ on sale");
		c260.setToolTipText("Low-Tier Skin on Sale");
		c250.setToolTipText("Summoner Icon");
		
		c1350.setSelected(true);
		c975.setSelected(true);
		c750.setSelected(true);
		c675.setSelected(true);
		c520.setSelected(true);
		c487.setSelected(true);
		c390.setSelected(true);
		c375.setSelected(true);
		c260.setSelected(true);
		
		contentPane.add(c3250);
		contentPane.add(c1820);
		contentPane.add(c1350);
		contentPane.add(c975);
		contentPane.add(c880);
		contentPane.add(c790);
		contentPane.add(c750);
		contentPane.add(c675);
		contentPane.add(c585);
		contentPane.add(c520);
		contentPane.add(c487);
		contentPane.add(c440);
		contentPane.add(c395);
		contentPane.add(c390);
		contentPane.add(c375);
		contentPane.add(c292);
		contentPane.add(c260);
		contentPane.add(c250);
	}
	
	private int[] rpValues() {
		int count = 0;
		int[] rpvals = {3250, 1820, 1350, 975, 880, 790, 750, 675, 585,
						520, 487, 440, 395, 390, 375, 292, 260, 250};
		for (int i = 0; i < boxes.size(); i++) {
			if (boxes.get(i).isSelected()) {
				count++;
			}
		}
		int[] vals = new int[count];
		count = 0;
		for (int i = 0; i < boxes.size(); i++) {
			if (boxes.get(i).isSelected()) {
				vals[count] = rpvals[i];
				count++;
			}
		}
		return vals;
	}
	
	private void findSolutions() {
		resList.clear();
		shown = 0;
		resultPane.removeAll();
		boolean go = false;
		final int[] RP = rpValues();
		HashMap<Integer, Counter> counterMap = new HashMap<Integer, Counter>();
		int nbrp;
		try {
			nbrp = Integer.parseInt(tfRP.getText());
			go = true;
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, "Invalid RP value", "Oh no!", JOptionPane.ERROR_MESSAGE);
			nbrp = 0;
		}
		int cntr = 1;
		counterMap.put(cntr, new Counter(0));
		while (!counterMap.isEmpty() && go) {
			int tmpRP = nbrp;
			while (tmpRP > 0) {
				tmpRP = nbrp;
				for (int i = 1; i <= cntr; i++) {
					tmpRP -= RP[counterMap.get(i).index];
				}
				if (tmpRP > 0) {
					counterMap.put(cntr + 1, new Counter(counterMap.get(cntr).index));
					cntr++;
				}
			}
			if (tmpRP == 0) {
				ArrayList<Integer> zero = new ArrayList<Integer>();
				for (int i = 1; i <= cntr; i++) {
					zero.add(RP[counterMap.get(i).index]);
				}
				resList.add(zero);
				if (resList.size() % 5000 == 0) {
					int resp = JOptionPane.showConfirmDialog(null, "The amount of solutions is over " + resList.size()+ "! " +
							"Would you like to stop, now?", "Hey listen!", JOptionPane.YES_NO_OPTION);
					if (resp == JOptionPane.YES_OPTION) {
						go = false;
					}
				}
			}
			while (!counterMap.isEmpty() && counterMap.get(cntr).index == RP.length - 1) {
				counterMap.remove(cntr);
				cntr--;
			}
			if (counterMap.isEmpty()) {
				break;
			} else {
				counterMap.get(cntr).index++;
			}
		}
	}
	
	private void showResults(int start, int number) {
		int count = start;
		shown += number;
		while (count < shown && count < resList.size()) {
			ArrayList<Integer> list = resList.get(count);
			int index = 0;
			int value = list.get(0);
			int valCount = 0;
			StringBuilder sb = new StringBuilder();
			sb.append(" ");
			while (index < list.size()) {
				if (list.get(index) != value) {
					sb.append(valCount + "x" + value + ", ");
					value = list.get(index);
					valCount = 1;
				} else {
					valCount++;
				}
				index++;
			}
			sb.append(valCount + "x" + value);
			JLabel resLbl = new JLabel(sb.toString());
			resLbl.setBounds(0, count * 18, resultPane.getWidth(), 18);
			if (count % 2 == 0) {
				resLbl.setBackground(Color.decode("#DDDDDD"));
				resLbl.setOpaque(true);
			}
			resultPane.add(resLbl);
			System.out.println(sb.toString());
			count++;
		}
		resultPane.setPreferredSize(new Dimension(resultPane.getWidth(), count * 18));
		resultPane.revalidate();
		resultPane.repaint();
		if (shown >= resList.size()) {
			btnMore.setVisible(false);
		} else {
			btnMore.setVisible(true);
		}
	}
	
	private class GoListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
				findSolutions();
				showResults(0, 10);
		}
	}
	
	private class MoreListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			showResults(shown, 10);
		}
	}
	
	private class Counter {
		public int index;
		
		public Counter(int ind) {
			index = ind;
		}
	}
}